package edu.stanford.bmir.protege.web.client.ui.ontology.stkos.enricher.option;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;

import edu.stanford.bmir.protege.web.client.dispatch.DispatchServiceManager;
import edu.stanford.bmir.protege.web.client.project.Project;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.StkosUtilServiceManager;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.MatchLevel;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.CancelEnricherResult;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.EnricherSource;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.EnrichmentOptions;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.EnrichmentResult;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.SourceThesaurus;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CancelEnricherAction;
import edu.stanford.bmir.protege.web.client.ui.library.msgbox.MessageBox;
import edu.stanford.bmir.protege.web.client.ui.library.msgbox.YesNoHandler;
import edu.stanford.bmir.protege.web.client.ui.ontology.stkos.common.GWTExtUtil;
import edu.stanford.bmir.protege.web.client.ui.ontology.stkos.common.interfaces.StkosCallBack;
import edu.stanford.bmir.protege.web.client.ui.projectmanager.DownloadProjectRequestHandler;
import edu.stanford.bmir.protege.web.client.ui.projectmanager.DownloadProjectRequestHandlerImpl;
import edu.stanford.bmir.protege.web.shared.project.GetAvailableProjectsAction;
import edu.stanford.bmir.protege.web.shared.project.GetAvailableProjectsResult;
import edu.stanford.bmir.protege.web.shared.project.ProjectDetails;

public class StkosEnricherOptionView extends Composite implements IsWidget,
		HasEnabled {

	public enum StkosEnricherOptionViewButtonType {
		AUTOENRICHER("自动丰富"),

		SHOWCLASS("显示类"),

		SHOWPROPERTY("显示属性"),

		EXPORTRESULT("导出结果"),

		CANCEL("取消")

		;

		private String text;

		private StkosEnricherOptionViewButtonType(String text) {
			this.text = text;
		}

		public String getButtonText() {
			return this.text;
		}
	}

	interface StkosEnricherOptionViewUiBinder extends
			UiBinder<HTMLPanel, StkosEnricherOptionView> {
	}

	private static StkosEnricherOptionViewUiBinder ourUiBinder = GWT
			.create(StkosEnricherOptionViewUiBinder.class);

	private Project project;

	private HTMLPanel rootElement;

	private List<SourceThesaurus> sourceThesaurus;

	private List<ProjectDetails> availableProjectDetails;

	private Map<StkosEnricherOptionViewButtonType, StkosCallBack> btnHandlers = new HashMap<StkosEnricherOptionViewButtonType, StkosCallBack>();

	// 数据来源
	@UiField
	protected RadioButton dataSourcesReferenceOntology;
	@UiField
	protected RadioButton dataSourcesThesaurus;
	@UiField
	protected RadioButton dataSourcesLiterature;

	// 参考本体
	@UiField
	protected ListBox referenceProject;

	// 参照词表
	@UiField
	protected ListBox referenceThesaurus;

	// 匹配方式
	@UiField
	protected RadioButton matchingWayExactMatching;
	@UiField
	protected RadioButton matchingWayFuzzyMatching;

	// 按钮
	@UiField
	protected Button btnAutoEnricher;
	@UiField
	protected Button btnShowClass;
	@UiField
	protected Button btnShowProperty;
	@UiField
	protected Button btnExportResult;
	/** 取消 */
	@UiField
	protected Button btnCancel;

	public StkosEnricherOptionView(Project project) {
		this.project = project;

		rootElement = ourUiBinder.createAndBindUi(this);
		initWidget(rootElement);

		registerBtnEvent();
		registerDataSourcesRadioEvent();

		setReferenceProjectItems();
		setReferenceThesaurusItems();
	}

	@Override
	public boolean isEnabled() {
		return true;
	}

	@Override
	public void setEnabled(boolean enabled) {
		btnAutoEnricher.setEnabled(enabled);
		btnShowClass.setEnabled(enabled);
		btnShowProperty.setEnabled(enabled);
		btnExportResult.setEnabled(enabled);
		btnCancel.setEnabled(enabled);
	}

	protected void registerBtnEvent() {
		ClickHandler clickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if (event.getSource().equals(btnAutoEnricher)) {
					autoEnricher();
				} else if (event.getSource().equals(btnShowClass)) {
					showClass();
				} else if (event.getSource().equals(btnShowProperty)) {
					showProperty();
				} else if (event.getSource().equals(btnExportResult)) {
					exportResult();
				} else if (event.getSource().equals(btnCancel)) {
					cancel();
				}
			}
		};

		btnAutoEnricher.addClickHandler(clickHandler);
		btnShowClass.addClickHandler(clickHandler);
		btnShowProperty.addClickHandler(clickHandler);
		btnExportResult.addClickHandler(clickHandler);
		btnCancel.addClickHandler(clickHandler);
	}

	public EnrichmentOptions getOptions() {
		EnrichmentOptions options = new EnrichmentOptions();
		// 数据来源
		if (dataSourcesReferenceOntology.getValue()) {
			options.setSource(EnricherSource.REF_PROJECT);
		}
		if (dataSourcesThesaurus.getValue()) {
			options.setSource(EnricherSource.THESAURUS);
		}
		if (dataSourcesLiterature.getValue()) {
			options.setSource(EnricherSource.DOC_TRIPLE);
		}
		// 参考本体
		if (EnricherSource.REF_PROJECT.equals(options.getSource())
				&& referenceProject.getSelectedIndex() != -1) {
			options.setRefProjectName(referenceProject
					.getValue(referenceProject.getSelectedIndex()));
		}
		// 参照词表
		if (EnricherSource.THESAURUS.equals(options.getSource())
				&& referenceThesaurus.getSelectedIndex() != -1) {
			try {
				options.setRefThesaurusID(Long.parseLong(referenceThesaurus
						.getValue(referenceThesaurus.getSelectedIndex())));
			} catch (Exception e) {
			}
		}
		// 文献三元组
		if (EnricherSource.DOC_TRIPLE.equals(options.getSource())) {
		}
		// 匹配力度
		if (matchingWayExactMatching.getValue()) {
			options.setMatchLevel(MatchLevel.CASE_INSENSITIVE);
		}
		if (matchingWayFuzzyMatching.getValue()) {
			options.setMatchLevel(MatchLevel.INCLUSIVE);
		}
		return options;
	}

	protected void autoEnricher() {
		GWTExtUtil.showProgressMonitor("提示", "程序正在处理、请稍候...");

		String projectName = project.getProjectId().getId();
		EnrichmentOptions options = getOptions();
		AsyncCallback<EnrichmentResult> callback = new AsyncCallback<EnrichmentResult>() {
			@Override
			public void onFailure(Throwable caught) {
				GWT.log("Stkosutil auto enricher failure.", caught);
				doAutoEnricherHandlers(null);
			}

			@Override
			public void onSuccess(EnrichmentResult result) {
				doAutoEnricherHandlers(result);
				btnCancel.setEnabled(true);
			}
		};
		StkosUtilServiceManager.getInstance().enrichOntology(projectName,
				options, callback);
	}

	protected void doAutoEnricherHandlers(EnrichmentResult result) {
		GWTExtUtil.hideProgressMonitor("提示", "程序处理完成!", 850);

		StkosCallBack handler = btnHandlers
				.get(StkosEnricherOptionViewButtonType.AUTOENRICHER);
		if (handler != null) {
			handler.onCallBack(result);
		}
	}

	protected void showClass() {
		StkosCallBack handler = btnHandlers
				.get(StkosEnricherOptionViewButtonType.SHOWCLASS);
		if (handler != null) {
			handler.onCallBack();
		}
	}

	protected void showProperty() {
		StkosCallBack handler = btnHandlers
				.get(StkosEnricherOptionViewButtonType.SHOWPROPERTY);
		if (handler != null) {
			handler.onCallBack();
		}
	}

	protected void exportResult() {
		DownloadProjectRequestHandler downloadProjectRequestHandler = new DownloadProjectRequestHandlerImpl();
		downloadProjectRequestHandler.handleProjectDownloadRequest(project
				.getProjectId());
		doExportHandler();
	}

	protected void cancel() {
		final String projectName = project.getProjectId().getId();
		// EnrichmentOptions eOpt = getOptions();
		YesNoHandler ynHandler = new YesNoHandler() {
			@Override
			public void handleYes() {
				cancelOperation(projectName);
			}

			@Override
			public void handleNo() {
			}
		};
		MessageBox.showYesNoConfirmBox("取消操作", "你确定要取消丰富操作吗?", ynHandler);
	}

	protected void cancelOperation(String projectName) {
		if (projectName == null) {
			MessageBox.showAlert("提示", "必要信息不完整,操作失败!");
			btnCancel.setEnabled(false);
			return;
		}

		GWTExtUtil.showProgressMonitor("提示", "程序正在处理、请稍候...");

		CancelEnricherAction action = new CancelEnricherAction();
		AsyncCallback<CancelEnricherResult> callback = new AsyncCallback<CancelEnricherResult>() {
			@Override
			public void onFailure(Throwable caught) {
				MessageBox.showAlert("取消操作", "取消操作处理失败、详情：" + caught);
				doCancelHandler(null);
			}

			@Override
			public void onSuccess(CancelEnricherResult result) {
				doCancelHandler(result);
			}
		};
		StkosUtilServiceManager.getInstance().cancelEnricher(projectName,
				action, callback);
	}

	protected void doCancelHandler(CancelEnricherResult result) {
		GWTExtUtil.hideProgressMonitor("提示", "程序处理完成!", 1);

		if (result != null) {
			MessageBox.showMessage("取消丰富操作成功", "共删除丰富类" + result.getDelClass()
					+ "个,丰富属性" + result.getDelProperty() + "个!");
		} else {
			MessageBox.showAlert("取消丰富操作结束", "返回结果为空!");
		}
		btnCancel.setEnabled(false);

		if (btnHandlers.get(StkosEnricherOptionViewButtonType.CANCEL) != null) {
			btnHandlers.get(StkosEnricherOptionViewButtonType.CANCEL)
					.onCallBack(result);
		}
	}

	protected void doExportHandler() {
		StkosCallBack handler = btnHandlers
				.get(StkosEnricherOptionViewButtonType.EXPORTRESULT);
		if (handler != null) {
			handler.onCallBack();
		}
	}

	protected void registerDataSourcesRadioEvent() {
		ValueChangeHandler<Boolean> valueChange = new ValueChangeHandler<Boolean>() {
			@Override
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				if (event.getSource().equals(dataSourcesReferenceOntology)) {
					showReferenceOntology();
				} else if (event.getSource().equals(dataSourcesThesaurus)) {
					showThesaurus();
				} else if (event.getSource().equals(dataSourcesLiterature)) {
					showLiterature();
				}
			}
		};

		dataSourcesReferenceOntology.addValueChangeHandler(valueChange);
		dataSourcesThesaurus.addValueChangeHandler(valueChange);
		dataSourcesLiterature.addValueChangeHandler(valueChange);
	}

	protected void showReferenceOntology() {
		Element el2 = rootElement
				.getElementById("stkosenricherReferenceThesaurusTr");
		el2.getStyle().setDisplay(Display.NONE);
		Element el3 = rootElement
				.getElementById("stkosenricherReferenceLiteratureTr");
		el3.getStyle().setDisplay(Display.NONE);

		Element el = rootElement
				.getElementById("stkosenricherReferenceProjectTr");
		el.getStyle().setProperty("display", "table-row");
	}

	protected void showThesaurus() {
		Element el2 = rootElement
				.getElementById("stkosenricherReferenceProjectTr");
		el2.getStyle().setDisplay(Display.NONE);
		Element el3 = rootElement
				.getElementById("stkosenricherReferenceLiteratureTr");
		el3.getStyle().setDisplay(Display.NONE);

		Element el = rootElement
				.getElementById("stkosenricherReferenceThesaurusTr");
		el.getStyle().setProperty("display", "table-row");
	}

	protected void showLiterature() {
		Element el2 = rootElement
				.getElementById("stkosenricherReferenceProjectTr");
		el2.getStyle().setDisplay(Display.NONE);
		Element el3 = rootElement
				.getElementById("stkosenricherReferenceThesaurusTr");
		el3.getStyle().setDisplay(Display.NONE);

		Element el = rootElement
				.getElementById("stkosenricherReferenceLiteratureTr");
		// el.getStyle().setProperty("display", "table-row");
		el.getStyle().setDisplay(Display.NONE);
	}

	protected void setReferenceProjectItems() {
		availableProjectDetails = null;
		referenceProject.clear();

		DispatchServiceManager.get().execute(new GetAvailableProjectsAction(),
				new AsyncCallback<GetAvailableProjectsResult>() {
					@Override
					public void onFailure(Throwable caught) {
						GWT.log("Getting project list failure.", caught);
					}

					@Override
					public void onSuccess(GetAvailableProjectsResult result) {
						if (result == null || result.getDetails() == null
								|| result.getDetails().size() == 0) {
							GWT.log("Can not find any source projects.");
						} else {
							availableProjectDetails = result.getDetails();
							String pid = project.getProjectId().getId();
							for (ProjectDetails pd : result.getDetails()) {
								try {
									if (!pd.isInTrash()
											&& !pd.getProjectId().getId()
													.equals(pid)) {
										referenceProject.addItem(pd
												.getDisplayName(), pd
												.getProjectId().getId());
									}
								} catch (Exception e) {
								}
							}
						}
					}
				});
	}

	protected void setReferenceThesaurusItems() {
		sourceThesaurus = null;
		referenceThesaurus.clear();

		AsyncCallback<List<SourceThesaurus>> callback = new AsyncCallback<List<SourceThesaurus>>() {
			@Override
			public void onFailure(Throwable caught) {
				GWT.log("Getting source thesaurus failure.", caught);
			}

			@Override
			public void onSuccess(List<SourceThesaurus> result) {
				sourceThesaurus = result;
				if (result == null || result.size() == 0) {
					GWT.log("Can not find any source thesaurus.");
					return;
				}
				referenceThesaurus.addItem("全部", "-1000");
				for (SourceThesaurus st : result) {
					if (st != null) {
						referenceThesaurus.addItem(st.getDisplayName(),
								st.getThesaurusId() + "");
					}
				}
			}
		};

		StkosUtilServiceManager.getInstance()
				.fetchSourceThesaurusList(callback);
	}

	public void setBtnHandler(StkosEnricherOptionViewButtonType type,
			StkosCallBack cb) {
		if (type == null || cb == null) {
			return;
		}
		btnHandlers.remove(type);
		btnHandlers.put(type, cb);
	}
}
